﻿using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;

namespace Nirvana
{
    [CustomEditor(typeof(UINameTable))]
    public class UINameTableEditor : Editor
    {
        private SerializedProperty binds;
        private ReorderableList reorderableList;
        private string searchname;
        private UINameTable.BindPair[] bindlist;
        private HashSet<int> NameKeyIndex = new HashSet<int>();
        private Dictionary<string, int> nameMap = new Dictionary<string, int>();
        private Dictionary<Object, int> widgetMap = new Dictionary<Object, int>();
        private GameObject addObj;
        private Object hadExistObj;
        private static GameObject curObj;
        private static GameObject refObj;

        public override void OnInspectorGUI()
        {
            serializedObject.Update();
            reorderableList.DoLayoutList();
            if (serializedObject.ApplyModifiedProperties())
            {
                this.InitUI();
            }
            UINameTable uinameTable = (UINameTable)this.target;
            GUILayout.BeginHorizontal(new GUILayoutOption[0]);
            this.addObj = (EditorGUILayout.ObjectField(this.addObj, typeof(GameObject), true, new GUILayoutOption[0]) as GameObject);
            if (GUILayout.Button("Add", new GUILayoutOption[0]))
            {
                if (this.addObj == null) return;
                this.hadExistObj = null;
                if (IsHaveSameObject(this.addObj))
                {
                    Debug.LogError("Duplicated Object");
                    return;
                }
                string txtname = this.addObj.name;
                int num = 0;
                while (uinameTable.FindTable(txtname))
                {
                    txtname += num;
                    num++;
                }
                Undo.RecordObject(uinameTable, "add to Name Table");
                serializedObject.Update();
                uinameTable.Add(txtname, this.addObj);
                serializedObject.ApplyModifiedProperties();
            }
            GUILayout.EndHorizontal();
            string searchvalue = EditorGUILayout.TextField("Search:", this.searchname, new GUILayoutOption[0]);
            if (string.IsNullOrEmpty(searchvalue))
            {
                searchname = null;
                bindlist = null;
            }
            else if(searchvalue != this.searchname)
            {
                this.searchname = searchvalue;
                bindlist = uinameTable.Search(searchvalue);
            }
            if(bindlist != null)
            {
                GUI.enabled = false;
                GUILayoutEx.BeginContents();
                foreach (UINameTable.BindPair bindPair in this.bindlist)
                {
                    EditorGUILayout.BeginHorizontal(new GUILayoutOption[0]);
                    EditorGUILayout.LabelField(bindPair.Name, new GUILayoutOption[0]);
                    EditorGUILayout.ObjectField(bindPair.Widget, bindPair.Widget.GetType(), true, new GUILayoutOption[0]);
                    EditorGUILayout.EndHorizontal();
                }
                GUILayoutEx.EndContents();
                GUI.enabled = true;
            }
            if (GUILayout.Button("Sort", new GUILayoutOption[0]))
            {
                Undo.RecordObject(uinameTable, "Sort Name Table");
                base.serializedObject.Update();
                uinameTable.Sort();
                base.serializedObject.ApplyModifiedProperties();
            }
        }

        private void OnEnable()
        {
            if (this.target == null) return;
            this.binds = serializedObject.FindProperty("binds");
            this.reorderableList = new ReorderableList(serializedObject, this.binds);
            this.reorderableList.drawHeaderCallback = new ReorderableList.HeaderCallbackDelegate(OnDrawHeadElement);
            this.reorderableList.elementHeight = EditorGUIUtility.singleLineHeight;
            this.reorderableList.drawElementCallback = new ReorderableList.ElementCallbackDelegate(OnDrawElement);
            this.InitUI();

        }

        private void OnDisable()
        {
            UINameTable uinameTable = this.target as UINameTable;
            if (null != uinameTable && uinameTable.gameObject == curObj)
            {
                curObj = null;
                refObj = null;
            }
        }

        private void InitUI()
        {
            this.NameKeyIndex.Clear();
            this.nameMap.Clear();
            this.widgetMap.Clear();
            for(int i=0;i< binds.arraySize; i++)
            {
                SerializedProperty arrayElementAtIndex = this.binds.GetArrayElementAtIndex(i);
                SerializedProperty nameSerial = arrayElementAtIndex.FindPropertyRelative("Name");
                SerializedProperty widgetSerial = arrayElementAtIndex.FindPropertyRelative("Widget");
                Object objRef = widgetSerial.objectReferenceValue;
                if (this.nameMap.ContainsKey(nameSerial.stringValue))
                {
                    this.NameKeyIndex.Add(this.nameMap[nameSerial.stringValue]);
                    this.NameKeyIndex.Add(i);
                }
                else
                {
                    this.nameMap.Add(nameSerial.stringValue, i);
                    if (objRef != null)
                    {
                        this.widgetMap.Add(objRef, i);
                    }
                }
            }


        }


        private void OnDrawHeadElement(Rect rect)
        {
            Rect position = new Rect(rect.x + 13f, rect.y, rect.width / 2f, EditorGUIUtility.singleLineHeight);
            Rect position2 = new Rect(rect.x + 10f + rect.width / 2f, rect.y, rect.width / 2f, EditorGUIUtility.singleLineHeight);
            GUI.Label(position, "Name");
            GUI.Label(position2, "Widget");
        }

        private void OnDrawElement(Rect rect, int index, bool isActive, bool isForce)
        {
            DrawElement(this.binds, rect, index, isActive, isForce);
        }


        private void DrawElement(SerializedProperty serial, Rect rect, int index, bool isActive, bool isForce)
        {
            SerializedProperty arrayElementAtIndex = serial.GetArrayElementAtIndex(index);
            bool flag = this.NameKeyIndex.Contains(index);
            Color color = GUI.color;
            if (flag) GUI.color = new Color(1f, 0.5f, 0.5f, 1f);
            SerializedProperty nameSerial = arrayElementAtIndex.FindPropertyRelative("Name");
            SerializedProperty widgetSerial = arrayElementAtIndex.FindPropertyRelative("Widget");
            if(widgetSerial.objectReferenceValue == this.hadExistObj)
            {
                GUI.color = new Color(0.2f, 1f, 1f, 1f);
            }
            else if(widgetSerial.objectReferenceValue  == this.addObj || widgetSerial.objectReferenceValue == refObj)
            {
                GUI.color = new Color(0.5f, 1f, 0.5f, 1f);
            }

            Rect rectname = new Rect(rect.x, rect.y, rect.width / 2f - 5f, EditorGUIUtility.singleLineHeight);
            Rect rectwidget = new Rect(rect.x + rect.width / 2f + 5f, rect.y, rect.width / 2f - 5f, EditorGUIUtility.singleLineHeight);
            EditorGUI.PropertyField(rectname, nameSerial, GUIContent.none);
            EditorGUI.PropertyField(rectwidget, widgetSerial, GUIContent.none);
            GUI.color = color;
        }

        private bool IsHaveSameObject(Object obj)
        {
            for (int i = 0; i < this.binds.arraySize; i++)
            {
                SerializedProperty arrayElementAtIndex = this.binds.GetArrayElementAtIndex(i);
                SerializedProperty serializedProperty = arrayElementAtIndex.FindPropertyRelative("Widget");
                if (serializedProperty.objectReferenceValue == obj)
                {
                    this.hadExistObj = obj;
                    return true;
                }
            }
            return false;
        }


    }
}

